/*
 * Copyright 2008 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "config/SkUserConfig.h"
#include "include/core/SkContourMeasure.h"
#include "include/core/SkPathMeasure.h"

SkPathMeasure::SkPathMeasure() {}

SkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale)
    : fPath(path), fForceClosed(forceClosed), fResScale(resScale) {
    fContour = fIter.next();
}

SkPathMeasure::~SkPathMeasure() {}

void SkPathMeasure::setPath(const SkPath* path, bool forceClosed) {
    fIter.reset(path ? *path : SkPath(), forceClosed);
    fContour = fIter.next();
    fPath = *path;
    fForceClosed = forceClosed;
}

SkScalar SkPathMeasure::getLength() {
    return fContour ? fContour->length() : 0;
//    return fOHPath ? SkFloatToScalar(OH_Drawing_PathGetLength(fOHPath.get(), fForceClosed)) : 0;
}

bool SkPathMeasure::getPosTan(SkScalar distance, SkPoint *position, SkVector *tangent) {
    [[unlikely]] if (fPath.IsOpaque()) {
        OH_Drawing_Point2D ohPosition, ohTangent;
        bool ret =
            OH_Drawing_PathGetPositionTangent(fPath, fForceClosed, SkScalarToFloat(distance), &ohPosition, &ohTangent);
        if (position) {
            *position = SkPoint::Make(SkFloatToScalar(ohPosition.x), SkFloatToScalar(ohPosition.y));
        }
        if (tangent) {
            *tangent = SkVector::Make(SkFloatToScalar(ohTangent.x), SkFloatToScalar(ohTangent.y));
        }
        return ret;
    }
    return fContour && fContour->getPosTan(distance, position, tangent);
}

bool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix, MatrixFlags flags) {
    [[unlikely]] if (fPath.IsOpaque()) {
        bool ret = false;
        if (matrix) {
            ret = OH_Drawing_PathGetMatrix(fPath, fForceClosed, SkScalarToFloat(distance), *matrix,
                                           ToOhMatrixFlags(flags));
        }
        return ret;
    }
    return fContour && fContour->getMatrix(distance, matrix, (SkContourMeasure::MatrixFlags)flags);
}

bool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo) {
    [[unlikely]] if (fPath.IsOpaque()) {
        OH_Drawing_Path* path = fPath;
        OH_Drawing_Path *dstPath = OH_Drawing_PathCreate();
        bool ret = false;
        if (OHDrawingAPI::OH_Drawing_PathGetSegment(path, fForceClosed, startD, stopD, startWithMoveTo, dstPath, &ret) != OH_DRAWING_SUCCESS || !ret) {
            OH_Drawing_PathDestroy(dstPath);
            return false;
        }
        // dst is also IsOpaque
        dst->setOHPath(dstPath);
        return ret;
    }
    return fContour && fContour->getSegment(startD, stopD, dst, startWithMoveTo);
}

bool SkPathMeasure::isClosed() {
    [[unlikely]] if (fPath.IsOpaque()) {
        return OH_Drawing_PathIsClosed(fPath, fForceClosed);
    }
    return fContour && fContour->isClosed();
}

bool SkPathMeasure::nextContour() {
    [[unlikely]] if (fPath.IsOpaque()) {
        RENDER_UNIMPLEMENTED;
        return false;
    }
    fContour = fIter.next();
    return !!fContour;
}

#ifdef SK_DEBUG
void SkPathMeasure::dump() {}
#endif
